package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.product.SkuInfoFeignClient;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;


@Slf4j
@Component
public class CartServiceImpl implements CartService {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    SkuInfoFeignClient skuInfoFeignClient;


    /**
     * 1、用户登录了。
     *      网关会带 userId头，网关会带 userTempId 头
     * 2、用户没登录。
     *      网关会带 userTempId头
     *
     * @param request
     * @return
     */
    @Override
    public String determinCartKey(HttpServletRequest request) {
        //1、请求头中如果有 userId ，这个就是当前登录的用户id
        String userId = request.getHeader("userId");
        if(!StringUtils.isEmpty(userId)){
            //说明用户登录，网关把id透传过来
            return RedisConst.CART_PREFIX + userId;
        }else {
            //说明用户没有登录，就用临时购物车
            String userTempId = request.getHeader("userTempId");

            return RedisConst.CART_TEMP_PREFIX+userTempId;
        }
    }

    @Override
    public String userCartKey(HttpServletRequest request) {
        String userId = request.getHeader("userId");
        if(!StringUtils.isEmpty(userId)){
            return RedisConst.CART_PREFIX + userId;
        }
        return null;
    }

    @Override
    public String tempCartKey(HttpServletRequest request) {
        String userId = request.getHeader("userTempId");
        if(!StringUtils.isEmpty(userId)){
            return RedisConst.CART_TEMP_PREFIX + userId;
        }
        return null;
    }


    /**
     * 给购物车保存数据
     * @param key
     * @param skuId
     * @param skuNum
     * @return
     */

    @Override
    public CartInfo addToCart(String key, Long skuId, Integer skuNum) {



        CartInfo result = null;


//        log.debug("");
        //在每个核心if进入以后都 log.debug("") 当前在什么流程，在进入每个方法的时候可以log.debug
//        log.info("");  //比较关键的信息
//        log.error(""); //所有的异常
        /**
         * String： key是str
         * Long： hashKey是Long
         * String：hashVal 是 String
         */
        BoundHashOperations<String, String, String> hashOps = getCart(key);

        //用户购物车和临时购物车过期时间不一样
        if(hashOps.hasKey(skuId.toString())){
            log.debug("购物车商品存在，数量叠加");
            //redis购物车已经有这个商品。商品数量叠加
            //1、先获取到这个商品信息
            String jsonStr = hashOps.get(skuId.toString());
            try {
                //从购物车获取到商品，反序列化
                result = new ObjectMapper().readValue(jsonStr, CartInfo.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            Integer num = result.getSkuNum();

            //修改购物车对象
            result.setSkuNum(num + skuNum);

            //注意要再次查询价格
            BigDecimal skuPrice = skuInfoFeignClient.getSkuPrice(skuId);
            result.setSkuPrice(skuPrice);

            //序列化
            String string = null;
            try {
                string = new ObjectMapper().writeValueAsString(result);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            hashOps.put(skuId.toString(),string);


        }else {
            //给购物车保存 cartInfo（SkuInfo） 信息
            //skuId，远程查询sku详情
            SkuInfo skuInfo = skuInfoFeignClient.getSkuInfo(skuId);

            //给redis中保存的加入到购物车的当前商品信息，把sku信息转成给购物车存的信息
            result = CartInfo.convertSkuInfoToCart(skuInfo);


            BigDecimal skuPrice = skuInfoFeignClient.getSkuPrice(skuId);

            //额外设置
            result.setSkuPrice(skuPrice);
            //设置数量
            result.setSkuNum(skuNum);

            String jsonStr = null;
            try {
                jsonStr = new ObjectMapper().writeValueAsString(result);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            hashOps.put(skuId.toString(),jsonStr);
            if(key.startsWith("cart:temp")){
                //临时购物车需要过期时间
                redisTemplate.expire(key,RedisConst.TEMP_CART_EXPIRE, TimeUnit.SECONDS);
            }

        }


        return result;
    }

    @Override
    public List<CartInfo> listCart(String userKey,String userTempKey) {

        List<CartInfo> result = null;
        /**
         * 1、如果用户登录了。key；默认是登录用户。购物车是用户购车。
         * 但是还带了 userTempId。代表没登录前用的临时车
         * 2、判断如果用户登录了，带了 userTempId，购物车需要合并
         */
        if(!StringUtils.isEmpty(userTempKey)){
            BoundHashOperations<String, String, String> cart = getCart(userTempKey);
            if(cart.size() > 0){
                //临时购物车有数据，拿到购物车的所有数据
                result = getCartInfoList(userTempKey);
            }
        }

        if(!StringUtils.isEmpty(userKey)){
            //说明用户登录了，把临时购物车的数据和用户购物车合并起来.
            if(!CollectionUtils.isEmpty(result)){
                //合并操作
                for (CartInfo info : result) {
                    //把临时购物车商品拿来添加到用户购物车中
                    addToCart(userKey,info.getSkuId(),info.getSkuNum());
                    //清空临时购物车
                    clearCart(userTempKey);
                }
            }

            //如果前面合并了，拿到的就是合并的结果
            result = getCartInfoList(userKey);
        }

        return result;
    }

    @Override
    public void clearCart(String key) {



        //大字符串
//        String abc = ````dsajldjasl
//        djaslkjdaslj
//        djaslkdjaslkjd
//        dashkdjahjkdajk
//        ```;
        //set 一个k=v

        //批量保存  MSET key1 "Hello" key2 "World"
//        redisTemplate.opsForValue().multiSet();
        redisTemplate.delete(key);
    }


    @Override
    public void checkCartItem(String key, Long skuId, Integer checked) {
        ObjectMapper objectMapper = new ObjectMapper();
        BoundHashOperations<String, String, String> cart = getCart(key);

        //获取到商品
        String json = cart.get(skuId.toString());
        CartInfo cartInfo = null;
        try {
            cartInfo = objectMapper.readValue(json, CartInfo.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        //设置状态
        cartInfo.setIsChecked(checked);


        String result = null;
        try {
            result = objectMapper.writeValueAsString(cartInfo);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        if(cart.size() <= 200){
            //TODO 每处保存数据的时候，判断是否超过数量限制
            cart.put(skuId.toString(),result);
        }else {
            throw  new RuntimeException("购物车数量限制");
        }



    }

    @Override
    public void deleteCartItem(String key, Long skuId) {
        BoundHashOperations<String, String, String> cart =
                getCart(key);

        cart.delete(skuId.toString());

    }

    @Override
    public List<CartInfo> listCheckCartInfo(String key) {
        ObjectMapper objectMapper = new ObjectMapper();
        //准备所有被选中的商品
        List<CartInfo> checked = new ArrayList<>();
        BoundHashOperations<String, String, String> cart = getCart(key);

        //返回的是每个购物车中的商品的json
        List<String> values = cart.values();
        if(!CollectionUtils.isEmpty(values)){
            for (String value : values) {
                CartInfo cartInfo = null;
                try {
                    cartInfo = objectMapper.readValue(value, CartInfo.class);
                    cartInfo.setCreateTime(null);
                    cartInfo.setUpdateTime(null);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                if(cartInfo.getIsChecked().intValue() == 1){
                    //被选中
                    checked.add(cartInfo);
                }
            }
        }

        return checked;
    }

    @Override
    public void deleteCartItemBatch(String key, List<String> skuIds) {
        BoundHashOperations<String, String, String> cart =
                getCart(key);

        //购物车的string
        String[] longs = skuIds.toArray(new String[skuIds.size()]);

        //移除指定的购物项，可变参数
        cart.delete(longs);
    }

    public BoundHashOperations<String, String, String> getCart(String key){
        return redisTemplate.boundHashOps(key);
    }


    /**
     * 获取购物车中所有商品
     * @param key
     * @return
     */
    public List<CartInfo> getCartInfoList(String key){

        //准备一个集合
        List<CartInfo> cartInfos = new ArrayList<>();

        //拿到购物车
        BoundHashOperations<String, String, String> cart =
                getCart(key);


        //拿到不是所有的key
        List<String> values = cart.values();
        if(!CollectionUtils.isEmpty(values)){
            //redis中这个购物车有数据
            for (String skuJson : values) {
                CartInfo cartInfo = null;
                try {
                    cartInfo = new ObjectMapper().readValue(skuJson, CartInfo.class);
                    //此处可以远程调用。再次获取商品价格
//                    CartInfo finalCartInfo = cartInfo;
//                    CompletableFuture.runAsync(()->{
//                        //线程没有更新购物车价格，也没事。
//                        BigDecimal skuPrice = skuInfoFeignClient.getSkuPrice(finalCartInfo.getSkuId());
//                        finalCartInfo.setSkuPrice(skuPrice);
//                        try {
//                            getCart(key).put(finalCartInfo.getSkuId().toString(),new ObjectMapper().writeValueAsString(finalCartInfo));
//                        } catch (JsonProcessingException e) {
//                        }
//                    });
//                    cartInfo.setCartPrice(); //当时存购物车的价格
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                cartInfos.add(cartInfo);
            }
        }

        return cartInfos;

    }
}
